home *** CD-ROM | disk | FTP | other *** search
/ SGI Developer Toolbox 6.1 / SGI Developer Toolbox 6.1 - Disc 4.iso / public / fax / src / faxd / Class2Recv.c++ < prev    next >
C/C++ Source or Header  |  1994-08-01  |  7KB  |  277 lines

  1. /*    $Header: /usr/people/sam/fax/faxd/RCS/Class2Recv.c++,v 1.59 1994/04/07 21:53:22 sam Rel $ */
  2. /*
  3.  * Copyright (c) 1990, 1991, 1992, 1993, 1994 Sam Leffler
  4.  * Copyright (c) 1991, 1992, 1993, 1994 Silicon Graphics, Inc.
  5.  *
  6.  * Permission to use, copy, modify, distribute, and sell this software and 
  7.  * its documentation for any purpose is hereby granted without fee, provided
  8.  * that (i) the above copyright notices and this permission notice appear in
  9.  * all copies of the software and related documentation, and (ii) the names of
  10.  * Sam Leffler and Silicon Graphics may not be used in any advertising or
  11.  * publicity relating to the software without the specific, prior written
  12.  * permission of Sam Leffler and Silicon Graphics.
  13.  * 
  14.  * THE SOFTWARE IS PROVIDED "AS-IS" AND WITHOUT WARRANTY OF ANY KIND, 
  15.  * EXPRESS, IMPLIED OR OTHERWISE, INCLUDING WITHOUT LIMITATION, ANY 
  16.  * WARRANTY OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE.  
  17.  * 
  18.  * IN NO EVENT SHALL SAM LEFFLER OR SILICON GRAPHICS BE LIABLE FOR
  19.  * ANY SPECIAL, INCIDENTAL, INDIRECT OR CONSEQUENTIAL DAMAGES OF ANY KIND,
  20.  * OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS,
  21.  * WHETHER OR NOT ADVISED OF THE POSSIBILITY OF DAMAGE, AND ON ANY THEORY OF 
  22.  * LIABILITY, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE 
  23.  * OF THIS SOFTWARE.
  24.  */
  25. #include <stdio.h>
  26. #include "Class2.h"
  27. #include "ModemConfig.h"
  28.  
  29. #include "t.30.h"
  30. #include <stdlib.h>
  31. #include <osfcn.h>
  32.  
  33. /*
  34.  * Recv Protocol for Class-2-style modems.
  35.  */
  36.  
  37. static const AnswerMsg answerMsgs[] = {
  38. { "+FCO",    4,
  39.   FaxModem::AT_NOTHING, FaxModem::OK,        FaxModem::CALLTYPE_FAX },
  40. { "+FDM",    4,
  41.   FaxModem::AT_NOTHING, FaxModem::OK,        FaxModem::CALLTYPE_DATA },
  42. { "+FHNG:",    6,
  43.   FaxModem::AT_NOTHING, FaxModem::NOCARRIER,FaxModem::CALLTYPE_ERROR },
  44. { "VCON",    4,
  45.   FaxModem::AT_NOTHING, FaxModem::OK,        FaxModem::CALLTYPE_VOICE },
  46. };
  47. #define    NANSWERS    (sizeof (answerMsgs) / sizeof (answerMsgs[0]))
  48.  
  49. const AnswerMsg*
  50. Class2Modem::findAnswer(const char* s)
  51. {
  52.     for (u_int i = 0; i < NANSWERS; i++)
  53.     if (strneq(s, answerMsgs[i].msg, answerMsgs[i].len))
  54.         return (&answerMsgs[i]);
  55.     return FaxModem::findAnswer(s);
  56. }
  57.  
  58. /*
  59.  * Begin a fax receive session.
  60.  */
  61. fxBool
  62. Class2Modem::recvBegin(fxStr& emsg)
  63. {
  64.     fxBool status = FALSE;
  65.     hangupCode[0] = '\0';
  66.     ATResponse r;
  67.     do {
  68.     switch (r = atResponse(rbuf, 3*60*1000)) {
  69.     case AT_NOANSWER:
  70.     case AT_NOCARRIER:
  71.     case AT_NODIALTONE:
  72.     case AT_ERROR:
  73.     case AT_TIMEOUT:
  74.     case AT_EMPTYLINE:
  75.         processHangup("70");
  76.         status = FALSE;
  77.         break;
  78.     case AT_FNSS:
  79.         // XXX parse and pass on to server
  80.         break;
  81.     case AT_FTSI:
  82.         recvCheckTSI(stripQuotes(skipStatus(rbuf)));
  83.         break;
  84.     case AT_FDCS:
  85.         if (recvDCS(rbuf))
  86.         status = TRUE;
  87.         break;
  88.     case AT_FHNG:
  89.         status = FALSE;
  90.         break;
  91.     }
  92.     } while (r != AT_TIMEOUT && r != AT_EMPTYLINE && r != AT_OK);
  93.     if (!status)
  94.     emsg = hangupCause(hangupCode);
  95.     return (status);
  96. }
  97.  
  98. /*
  99.  * Process a received DCS.
  100.  */
  101. fxBool
  102. Class2Modem::recvDCS(const char* cp)
  103. {
  104.     if (parseClass2Capabilities(skipStatus(cp), params)) {
  105.     setDataTimeout(60, params.br);
  106.     FaxModem::recvDCS(params);
  107.     return (TRUE);
  108.     } else {                // protocol botch
  109.     processHangup("72");        // XXX "COMREC error"
  110.     return (FALSE);
  111.     }
  112. }
  113.  
  114. /*
  115.  * Signal that we're ready to receive a page
  116.  * and then collect the data.  Return the
  117.  * received post-page-message.
  118.  */
  119. fxBool
  120. Class2Modem::recvPage(TIFF* tif, int& ppm, fxStr& emsg)
  121. {
  122.     ppm = PPM_EOP;
  123.     hangupCode[0] = 0;
  124.     if (vatFaxCmd(AT_NOTHING, "DR")) {
  125.     ATResponse r;
  126.     while ((r = atResponse(rbuf, conf.pageStartTimeout)) != AT_CONNECT)
  127.         switch (r) {
  128.         case AT_FDCS:            // inter-page DCS
  129.         (void) recvDCS(rbuf);
  130.         break;
  131.         case AT_TIMEOUT:
  132.         case AT_EMPTYLINE:
  133.         case AT_ERROR:
  134.         case AT_NOCARRIER:
  135.         case AT_NODIALTONE:
  136.         case AT_NOANSWER:
  137.         case AT_FHNG:            // remote hangup
  138.         goto bad;
  139.         }
  140.     protoTrace("RECV: begin page");
  141.     /*
  142.      * NB: always write data in LSB->MSB for folks that
  143.      *     don't understand the FillOrder tag!
  144.      */
  145.     recvSetupPage(tif, group3opts, FILLORDER_LSB2MSB);
  146.     int ppr;
  147.     if (recvPageData(tif) && recvPPM(tif, ppr)) {
  148.         // XXX deal with PRI interrupts
  149.         if (ppr & 1) {
  150.         TIFFWriteDirectory(tif);
  151.         countPage();
  152.         } else {
  153.         recvResetPage(tif);        // reset to overwrite data
  154.         }
  155.         if (waitFor(AT_FET)) {
  156.         ppm = atoi(skipStatus(rbuf));
  157.         tracePPM("RECV recv", ppm);
  158.         tracePPR("RECV send", ppr);
  159.         return (waitFor(AT_OK));
  160.         }
  161.     }
  162.     }
  163. bad:
  164.     if (hangupCode[0] == 0)
  165.     processHangup("90");        // "Unspecified Phase C error"
  166.     emsg = hangupCause(hangupCode);
  167.     return (FALSE);
  168. }
  169.  
  170. /*
  171.  * Write received data to the current file.
  172.  */
  173. void
  174. Class2Modem::recvData(TIFF* tif, u_char* bp, int n)
  175. {
  176.     /*
  177.      * Always put data out to the file in LSB2MSB bit order.
  178.      * We do this because some TIFF readers (mostly on the PC)
  179.      * don't understand MSB2LSB and/or the FillOrder tag.
  180.      */
  181.     if (conf.recvFillOrder != FILLORDER_LSB2MSB)
  182.     TIFFReverseBits(bp, n);
  183.     FaxModem::recvPageData(tif, bp, n);
  184. }
  185.  
  186. /*
  187.  * Receive Phase C data using the Class 2 ``stream interface''.
  188.  */
  189. fxBool
  190. Class2Modem::recvPageData(TIFF* tif)
  191. {
  192.     if (flowControl == FLOW_XONXOFF)
  193.     (void) setXONXOFF(FLOW_NONE, FLOW_XONXOFF, ACT_FLUSH);
  194.     (void) putModem(&recvDataTrigger, 1);  // initiate data transfer
  195.  
  196.     startPageRecv();
  197.  
  198.     fxBool prematureEOF = recvPageDLEData(tif);
  199.  
  200.     // be careful about flushing here -- otherwise we lose +FPTS codes
  201.     if (flowControl == FLOW_XONXOFF)
  202.     (void) setXONXOFF(FLOW_XONXOFF, FLOW_CURRENT, ACT_DRAIN);
  203.     endPageRecv(params);
  204.  
  205.     if (prematureEOF) {
  206.     processHangup("91");            // "Missing EOL after 5 seconds"
  207.     return (FALSE);
  208.     }
  209.     return (TRUE);
  210. }
  211.  
  212. fxBool
  213. Class2Modem::recvPPM(TIFF* tif, int& ppr)
  214. {
  215.     for (;;) {
  216.     switch (atResponse(rbuf, conf.pageDoneTimeout)) {
  217.     case AT_OK:
  218.         modemTrace("protocol botch: OK with +FPTS:");
  219.         /* fall thru... */
  220.     case AT_TIMEOUT:
  221.     case AT_EMPTYLINE:
  222.     case AT_NOCARRIER:
  223.     case AT_NODIALTONE:
  224.     case AT_NOANSWER:
  225.     case AT_ERROR:
  226.         processHangup("50");
  227.         return (FALSE);
  228.     case AT_FPTS:
  229.         return parseFPTS(tif, skipStatus(rbuf), ppr);
  230.     case AT_FET:
  231.         protoTrace("MODEM protocol botch: +FET: without +FPTS:");
  232.         processHangup("100");        // "Unspecified Phase D error"
  233.         return (FALSE);
  234.     case AT_FHNG:
  235.         waitFor(AT_OK);            // resynchronize modem
  236.         return (FALSE);
  237.     }
  238.     }
  239. }
  240.  
  241. fxBool
  242. Class2Modem::parseFPTS(TIFF* tif, const char* cp, int& ppr)
  243. {
  244.     int lc = 0;
  245.     int blc = 0;
  246.     int cblc = 0;
  247.     ppr = 0;
  248.     if (sscanf(cp, "%d,%d,%d,%d", &ppr, &lc, &blc, &cblc) > 0) {
  249.     // NB: ignore modem line count, always use our own
  250.     TIFFSetField(tif, TIFFTAG_IMAGELENGTH, getRecvEOLCount());
  251.     TIFFSetField(tif, TIFFTAG_CLEANFAXDATA, blc ?
  252.         CLEANFAXDATA_REGENERATED : CLEANFAXDATA_CLEAN);
  253.     if (blc) {
  254.         TIFFSetField(tif, TIFFTAG_BADFAXLINES, (u_long) blc);
  255.         TIFFSetField(tif, TIFFTAG_CONSECUTIVEBADFAXLINES, cblc);
  256.     }
  257.     return (TRUE);
  258.     } else {
  259.     modemTrace("protocol botch: \"%s\"; can not parse line count", cp);
  260.     processHangup("100");        // "Unspecified Phase D error"
  261.     return (FALSE);
  262.     }
  263. }
  264.  
  265. /*
  266.  * Complete a receive session.
  267.  */
  268. fxBool
  269. Class2Modem::recvEnd(fxStr&)
  270. {
  271.     if (isNormalHangup())
  272.     (void) vatFaxCmd(AT_NOCARRIER, "DR");        // wait for DCN
  273.     else
  274.     (void) abort();
  275.     return (TRUE);
  276. }
  277.